package com.pricl.biz.upload.manager;

import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springside.modules.mapper.BeanMapper;

import com.aliyun.oss.OSSClient;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.pricl.biz.file.constant.FileStatusConstant;
import com.pricl.biz.file.dao.FileInfoDao;
import com.pricl.biz.file.entity.FileInfo;
import com.pricl.biz.file.service.FileManagerService;
import com.pricl.biz.upload.FileItem;
import com.pricl.biz.upload.UploadFileManager;
import com.pricl.biz.upload.exception.UnsupportedFileLengthException;
import com.pricl.biz.upload.exception.UnsupportedFormatException;
import com.pricl.biz.util.OSSUtils;
import com.pricl.frame.common.utils.FileManagerUtils;
import com.pricl.frame.common.utils.Utils;
import com.pricl.frame.core.constants.FileManagerConstants;

/**
 * <ol>
 * <li>文件上传实用类</li>
 * <ol>
 * 
 * @author jackzhong
 * @since 2014年10月30日上午1:30:12
 */
public abstract class AbstractUploadFileManager implements UploadFileManager {

	private final Logger logger = LoggerFactory.getLogger(getClass());

	/**
	 * 判断是否支持生成缩略图
	 */
	protected boolean isSupperThumbnail = false;

	/**
	 * 判断是否支持压缩
	 */
	protected boolean isCompressed = false;

	/**
	 * 默认的缩略图大小
	 */
	private int defaultThumbnailSize = 150;

	/**
	 * 默认允许上传文件大小
	 */
	protected long defalutAllowFileSize = 10737418240L;

	/**
	 * 系统文件配置
	 */
	@Resource(name="systemConfigManager")
	protected SystemConfigManager systemConfigManager;

	/**
	 * 文件管理服务类
	 */
	@Autowired
	protected FileManagerService fileManagerService;
	
	@Autowired
	protected FileInfoDao fileInfoDao;
	
//	/**
//	 * 记录业务日志
//	 */
//	@Autowired
//	protected BusinessLogger businessLogger;

	/**
	 * 获取上传文件根路径
	 * 
	 * @return
	 */
	public String getFileUploadDirectory() {
		return systemConfigManager.getSystemConfigValueByConfigCode(FileManagerConstants.FILE_UPLOAD_DIRECTORY);
	}

	/**
	 * 获取图片相对路径
	 * 
	 * @return
	 */
	public String getImageUploadRelativePath() {
		return FileManagerConstants.UPLOAD_IMAGE_PREFIX + FileManagerConstants.FILE_DECOLLATOR + FileManagerUtils.createRelativePath();
//		return FileManagerConstants.FILE_DECOLLATOR + FileManagerConstants.UPLOAD_IMAGE_PREFIX + FileManagerConstants.FILE_DECOLLATOR + FileManagerUtils.createRelativePath();
	}

	/**
	 * 获取上传图片绝对路径
	 * 
	 * @return
	 */
	public String getImageUploadDirectory() {
		return getFileUploadDirectory() + getImageUploadRelativePath();
	}

	/**
	 * 获取视频相对路径
	 * 
	 * @return
	 */
	public String getVideoUploadRelativePath() {
		return FileManagerConstants.FILE_DECOLLATOR + FileManagerConstants.UPLOAD_VIDEO_PREFIX + FileManagerConstants.FILE_DECOLLATOR + FileManagerUtils.createRelativePath();
	}

	/**
	 * 获取视频绝对路径
	 * 
	 * @return
	 */
	public String getVideoUploadDirectory() {
		return getFileUploadDirectory() + getVideoUploadRelativePath();
	}

	/**
	 * 获取音频相对路径
	 * 
	 * @return
	 */
	public String getAudioUploadRelativePath() {
		//return FileManagerConstants.FILE_DECOLLATOR + FileManagerConstants.UPLOAD_AUDIO_PREFIX + FileManagerConstants.FILE_DECOLLATOR + FileManagerUtils.createRelativePath();
		return FileManagerConstants.UPLOAD_AUDIO_PREFIX + FileManagerConstants.FILE_DECOLLATOR + FileManagerUtils.createRelativePath();
	}

	/**
	 * 获取音频绝对路径
	 * 
	 * @return
	 */
	public String getAudioUploadDirectory() {
		return getFileUploadDirectory() + getAudioUploadRelativePath();
	}

	/**
	 * 获取文档相对路径
	 * 
	 * @return
	 */
	public String getDocUploadRelativePath() {
		//return FileManagerConstants.FILE_DECOLLATOR + FileManagerConstants.UPLOAD_DOC_PREFIX + FileManagerConstants.FILE_DECOLLATOR + FileManagerUtils.createRelativePath();
		//TODO 修改文件存放到oss 20170419
		return  FileManagerConstants.UPLOAD_DOC_PREFIX + FileManagerConstants.FILE_DECOLLATOR + FileManagerUtils.createRelativePath();
	}
	
	/**
	 * 获取压缩包相对路径
	 * 
	 * @return
	 */
	public String getZipUploadRelativePath() {
		//return FileManagerConstants.FILE_DECOLLATOR + FileManagerConstants.UPLOAD_DOC_PREFIX + FileManagerConstants.FILE_DECOLLATOR + FileManagerUtils.createRelativePath();
		//TODO 修改文件存放到oss 20170419
		return  FileManagerConstants.UPLOAD_ZIP_PREFIX + FileManagerConstants.FILE_DECOLLATOR + FileManagerUtils.createRelativePath();
	}
	
	
	/**
	 * 获取压缩包相对路径
	 * 
	 * @return
	 */
	public String getHelpUploadRelativePath() {
		//return FileManagerConstants.FILE_DECOLLATOR + FileManagerConstants.UPLOAD_DOC_PREFIX + FileManagerConstants.FILE_DECOLLATOR + FileManagerUtils.createRelativePath();
		//TODO 修改文件存放到oss 20170419
		return  FileManagerConstants.UPLOAD_ZIP_PREFIX + FileManagerConstants.FILE_DECOLLATOR + FileManagerUtils.createRelativePath();
	}

	/**
	 * 获取文档绝对路径
	 * 
	 * @return
	 */
	public String getDocUploadDirectory() {
		return getFileUploadDirectory() + getDocUploadRelativePath();
	}

	/**
	 * 获取上传临时相对路径
	 * 
	 * @return
	 */
	public String getTempUploadRelativePath() {
		return FileManagerConstants.FILE_DECOLLATOR + FileManagerConstants.UPLOAD_TEMP_PREFIX + FileManagerConstants.FILE_DECOLLATOR + FileManagerUtils.createRelativePath();
	}

	/**
	 * 获取上传临时绝对路径
	 * 
	 * @return
	 */
	public String getTempUploadDirectory() {
		return getFileUploadDirectory() + getTempUploadRelativePath();
	}

	/**
	 * 获取上传临时相对路径
	 * 
	 * @return
	 */
	public String getThumbnailUploadRelativePath() {
		return FileManagerConstants.FILE_DECOLLATOR + FileManagerConstants.UPLOAD_THUMBNAIL_PREFIX + FileManagerConstants.FILE_DECOLLATOR + FileManagerUtils.createRelativePath();
	}

	/**
	 * 获取上传图片缩略图大小
	 * 
	 * @return
	 */
	public int getThumbnailSize() {
		int thumbnailSize = defaultThumbnailSize;
		try {
			String thumbnailSizeStr = systemConfigManager.getSystemConfigValueByConfigCode(FileManagerConstants.UPLOAD_THUMBNAIL_SIZE);
			if (!StringUtils.isEmpty(thumbnailSizeStr)) {
				thumbnailSize = Integer.valueOf(thumbnailSizeStr);
			}
		} catch (Exception ex) {
			// 忽略
			thumbnailSize = defaultThumbnailSize;
		}
		return thumbnailSize;
	}

	/**
	 * 获取上传临时绝对路径
	 * 
	 * @return
	 */
	public String getThumbnailUploadDirectory() {
		return getFileUploadDirectory() + getThumbnailUploadRelativePath();
	}

	/**
	 * 获取允许文件的扩展名
	 * 
	 * @return
	 */
	public Set<String> getAllowFileExtensions(String allowFileExString) {
		String imageAllowFormatStr = systemConfigManager.getSystemConfigValueByConfigCode(allowFileExString);
		if (StringUtils.isEmpty(imageAllowFormatStr))
			return Sets.newHashSet();
		return Sets.newHashSet(imageAllowFormatStr.split(","));
	}

	/**
	 * 获取允许上传文件的大小
	 * 
	 * @return
	 */
	protected long getAllowFileSize(String allowFileSize) {
//		String imageAllowSizeStr = systemConfigManager.getSystemConfigValueByConfigCode(allowFileSize);
//		if (StringUtils.isEmpty(imageAllowSizeStr)) {
//			return defalutAllowFileSize;
//		}
//		try {
//			return Integer.valueOf(imageAllowSizeStr);
//		} catch (Exception ex) {
//			// 忽略
//			return defalutAllowFileSize;
//		}
		return defalutAllowFileSize;
	}

	/**
	 * 获取文件上传的相对路径
	 * 
	 * @return
	 */
	public abstract String getFileUploadRelativePath();

	/**
	 * 处理MultipartHttpServletRequest上传
	 * 
	 * @param request
	 * @param response
	 */
	
	public List<FileItem> handlerUpload(MultipartHttpServletRequest request) {
		if (request == null || request.getFileNames() == null)
			return null;
		// 获取当前登录的用户
		
		// 迭代上传的文件对象
		Iterator<String> itr = request.getFileNames();
		// 文件对象
		List<FileItem> list = Lists.newArrayList();
		// 迭代上传对象
		MultipartFile mpf;
		while (itr.hasNext()) {
			mpf = request.getFile(itr.next());
			// get the extension
			Set<String> validExtensions = getAllowFileExtensions();
			// Check the extension
			String extension = FileManagerUtils.getFileExtension(mpf.getOriginalFilename());
			if (!validExtensions.contains(extension)) {
				logger.error("============================>> Unsupported file extension:{}", extension);
				throw new UnsupportedFormatException("Unsupported file extension " + extension);
			}
			long fileSize = mpf.getSize();
			long allowFileSize = getAllowFileSize();
			if (fileSize > allowFileSize) {
				logger.error("============================>> Unsupported file size:{}", fileSize);
				throw new UnsupportedFileLengthException("Unsupported file size " + fileSize);
			}
			//
			 
			// 新的文件名
			FileInfo fileInfo =	createFileInfo(mpf);
			String fileUploadFullDirectory = null;
			String newFilename;
			String contentType = mpf.getContentType();
			fileUploadFullDirectory = fileInfo.getPath();
			newFilename = fileInfo.getId() + "." + fileInfo.getExtName();
			
			if (logger.isDebugEnabled()) {
				logger.debug("============================>> File Upload Full Directory:{},File Extension:{},File Size:{}", fileUploadFullDirectory + newFilename, extension, fileSize);
			}
			
			/**
			 * 图片上传到阿里云OSS服务
			 */
			try {
				OSSClient client = OSSUtils.getOSSClient();
				String result = OSSUtils.uploadObject2OSS2(client, fileInfo, mpf.getInputStream(), fileInfo.getLength());
				FileItem fileItem = null ;
				if(result!=null){
					fileInfoDao.insert(fileInfo);
					fileItem = BeanMapper.map(fileInfo, FileItem.class);
				}
				// 返回文件上传的明细
				list.add(fileItem);
			} catch (Exception e) {
				logger.error("============================>> Could not upload file " + mpf.getOriginalFilename(), e);
				throw new RuntimeException("Could not upload file " + mpf.getOriginalFilename(), e);
			}
		}
		return list;
	}

	/**
	 * @param isSupperThumbnail
	 *            the isSupperThumbnail to set
	 */
	public void setSupperThumbnail(boolean isSupperThumbnail) {
		this.isSupperThumbnail = isSupperThumbnail;
	}

	/**
	 * @param isCompressed
	 *            the isCompressed to set
	 */
	public void setCompressed(boolean isCompressed) {
		this.isCompressed = isCompressed;
	}
	
	
	/**
	 * 
	 * @ClassName createFileInfo 
	 * @Description   
	 * @author zbs  @date 2017年8月21日 @company 车资道科技 
	 * 
	 * @return 构建fileInfo
	 */
	public FileInfo createFileInfo(MultipartFile file){
		FileInfo fileInfo = new FileInfo();
		fileInfo.setOname(file.getOriginalFilename());
		fileInfo.setContentType(file.getContentType());
		fileInfo.setLength(file.getSize());
		if (fileInfo.getId() == null || fileInfo.getId().isEmpty()) {
			fileInfo.setId(Utils.uuid());
		}
		String[] names = formatName(fileInfo.getOname());
		if (fileInfo.getName() == null || fileInfo.getName().isEmpty()) {
			fileInfo.setName(names[0]);
		}
		fileInfo.setExtName(names[1]);
		
		// 构建上传路径
		String storageDirectory = getFileUploadDirectory();
		String relativePath = getFileUploadRelativePath();
		StringBuffer fileUploadFullDirectorySb = new StringBuffer();
		fileUploadFullDirectorySb.append(storageDirectory).append(relativePath).append(FileManagerConstants.FILE_DECOLLATOR);
		String fileUploadFullDirectory = fileUploadFullDirectorySb.toString();
		fileInfo.setPath(fileUploadFullDirectory);
		// 创建日期
		fileInfo.setCreatedDt(new Date());
		// 状态
		fileInfo.setStatus(FileStatusConstant.normal);
		return fileInfo;
	}
	
	public String[] formatName(String name) {
		if (name == null || name.isEmpty()) {
			return new String[] { "", "" };
		}
		int lastDot = name.lastIndexOf('.');
		if (lastDot == -1) {
			return new String[] { "", "" };
		}
		return new String[] { name.substring(0, lastDot), name.substring(lastDot + 1) };
	}
}
